package 力扣.堆;

import java.util.Arrays;

public class 堆排序 {
    public static void main(String []args){
        int []arr = {9,8,7,6,5,4,3,2,1};
//        int []arr = {6,4,5,3,2,4,10};
//        int []arr = {1,4,5,1,3,4,2,6};
//        int []arr = {4,6,8,5,9};
        sort(arr);
        System.out.println(Arrays.toString(arr));
    }
    public static void sort(int []arr){
        //1.构建大顶堆（父节点总是大于子节点），以便每次排序时每次下沉都能得到最大的元素
        for(int i=(arr.length-1-1 >> 1) ;i>=0;i--){//第一个非叶子结点开始
            //从第一个非叶子结点（最后一个节点的父节点）从下至上，从右至左调整结构
            adjustHeap(arr,i,arr.length);
//            adjustHeap(arr,0,arr.length);
        }
        //2.调整堆结构+交换堆顶元素与末尾元素
        for(int j=arr.length-1;j>0;j--){
            swap(arr,0,j);//将堆顶元素与末尾元素进行交换
            adjustHeap(arr,0,j);//重新对堆进行调整
        }

    }

    /**
     * 调整局部大顶堆（下沉操作）
     * @param arr
     * @param i
     * @param length
     */
    public static void adjustHeap2(int []arr,int i,int length){
        int temp = arr[i];//先取出当前元素i
        for(int k=i*2+1;k<length;k=k*2+1){//从i结点的左子结点开始，也就是2i+1处开始
            if(k+1<length && arr[k]<arr[k+1]){//如果左子结点小于右子结点，k指向右子结点
                k++;
            }
            if(arr[k] > temp){//如果子节点大于父节点，将子节点值赋给父节点（不用进行交换）
                arr[i] = arr[k];
                i = k;
            }else{
                break;
            }
        }
        arr[i] = temp;//将temp值放到最终的位置
    }
    private static void adjustHeap(int[] nums, int i,int length) {
        int te = nums[i];
        for (int j = i * 2 + 1 ; j < length; j = ((j << 1) + 1)) {
            if (j < length - 1 && nums[j+1] < nums[j]){
                j++;
            }
            if (nums[j] < te){
                nums[i] = nums[j];
                i = j;
            }else {
                break;
            }
        }
        nums[i] = te;
    }
    /**
     * 交换元素
     */
    public static void swap(int []arr,int a ,int b){
       int temp=arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }
}
